#pragma once

#include <windows.h>
#include <string>
#include <vector>
#include "fs_types.h"

#define MAX_URL 1024

class FSOperationClient
{
public:
    FSOperationClient(const char* svrHost, const char* logHost);
    virtual ~FSOperationClient();
    
    HResult GetSubdirInfo(DIR_ID parentID, const std::string& dirName, OUT DIR_INFO& dirInfo);
    
    HResult GetSubdirInfos(DIR_ID parentID, OUT std::vector<DIR_INFO>& dirInfos);
    
    HResult GetSubfileInfo(DIR_ID parentID, const std::string& fileName, OUT FILE_INFO& fileInfo);
    
    HResult GetSubfileInfos(DIR_ID parentID, OUT std::vector<FILE_INFO>& fileInfos);
    
    HResult ReadFile(const FILE_INFO& sourceInfo, uint64_t offset, OUT int8_t* buf, size_t readCount, OUT size_t& actualReadCount);
    
    /* Write Operations */
    HResult CreateNewDir(DIR_ID parentID, const std::string& newDirName, OUT DIR_INFO& newDirInfo);
    
    HResult CreateLinkDir(DIR_ID parentID, const std::string& newDirName, DIR_ID sourceID, OUT DIR_INFO& newDirInfo);
    
    HResult RenameDir(DIR_ID parentID, const std::string& orgDirName, const std::string& newDirName, OUT DIR_INFO& newDirInfo);
    
    HResult DeleteDir(DIR_ID parentID, const std::string& orgDirName); // in recursion 
    
    HResult CreateNewFile(DIR_ID parentID, const std::string& newFileName, const int8_t* buf, size_t bufLen, OUT FILE_INFO& newFileInfo);
    
    HResult CreateNewFile(DIR_ID parentID, const std::string& newFileName, const std::wstring& localFileName, OUT FILE_INFO& newFileInfo);
    
    HResult CreateLinkFile(DIR_ID parentID, const std::string& newFileName, const FILE_INFO& sourceInfo, OUT FILE_INFO& newFileInfo);
    
    HResult RenameFile(DIR_ID parentID, const std::string& orgFileName, const std::string& newFileName, OUT FILE_INFO& newFileInfo);
    
    HResult DeleteAFile(DIR_ID parentID, const std::string& orgFileName);

    struct OpLog
    {
        OpLog()
        {
            _ownerid = 0;
            _userid = 0;
            SYSTEMTIME time;
            GetLocalTime(&time);
            char buf[128];
            _snprintf(buf, 128, "%d-%d-%d %d:%d:%d", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond);
            _optime = buf;
        }
        USER_ID     _ownerid;
        USER_ID     _userid;
        std::string _userName;
        std::string _appName;
        std::string _dirName;
        std::string _client;
        std::string _sourceFile;
        std::string _targetFile;
        std::string _content;
        std::string _optime;

        std::string getData() const
        {
            char buf[4096];
            _snprintf_s(buf, 4096,
                "ownerid=%u&userid=%u&username=%s&appname=%s&dirname=%s&client=%s&source=%s&target=%s&content=%s&optime=%s",
                _ownerid, _userid, _userName.c_str(), _appName.c_str(), _dirName.c_str(),
                _client.c_str(), _sourceFile.c_str(), _targetFile.c_str(), _content.c_str(),
                _optime.c_str());
            return std::string(buf);
        }
    };

    HResult WriteOpLog(const OpLog& log);
private:
    struct WriteDataStruct
    {
        std::string _data;

        WriteDataStruct()
        {
            _data.resize(0);
        }

        ~WriteDataStruct()
        {
        }
    };

    HResult MakeRequest(const char* query_url, OUT std::string& data, const char* postData = NULL, size_t len = 0);
    static size_t WriteCallback( void *ptr, size_t size, size_t nmemb, void *userdata);
private:
    std::string _svrHost;
    std::string _logHost;
};
